/**
 * Vue 核心流程
 * 1.创造了响应式数据
 * 2.根据模板转化成ast语法树
 * 3.将ast语法树转化成render函数
 * 4.后续每次更新数据都只执行render函数，自动更新页面
 */
import {createElementVNode, createTextVNode} from "./vdom/index.js";
import Watcher from "./observe/watcher.js";
import {patch} from "./vdom/patch.js";

export function initLifeCycle(Vue){
    // _c 的返回值就是 render 函数的返回值
    Vue.prototype._c = function (){
        // 创建一个虚拟DOM
        return createElementVNode(this,...arguments)
    }

    // _v 的返回值给 _c 使用
    Vue.prototype._v = function (){
        return createTextVNode(this,...arguments)
    }

    // _s 的返回值给 _v 使用
    Vue.prototype._s = function (value){
        return typeof value === "object" ? JSON.stringify(value) : value
    }

    // _render函数的返回值会作为参数传递给 _update
    Vue.prototype._render = function (){
        return this.$options.render.call(this)
    }

    // 更新视图方法
    Vue.prototype._update = function (vnode){
        const vm = this
        const el = vm.$el
        const preVNode = vm._vnode
        vm._vnode = vnode
        if(preVNode){
            // 第二个渲染，用两个虚拟节点进行diff
            vm.$el = patch(preVNode,vnode)
        }else{
            // 第一次渲染页面，用虚拟节点直接覆盖真实DOM
            vm.$el = patch(el,vnode)
        }
    }
}


// 挂载页面
export function mountComponent(vm,el){
    vm.$el = el
    // 1.调用render方法产生虚拟节点
    // 2.根据虚拟DOM产生真实DOM
    // 3.插入到el中去

    const updateComponent = ()=> {
        vm._update(vm._render())
    }
    // 初始化渲染
    new Watcher(vm,updateComponent)
}


